package de.jmda.core.util.classpath;

import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.log4j.Logger;
import org.junit.Test;

import de.jmda.core.util.RuntimeUtil;

public class JUTClasspathUtil
{
	private final static Logger LOGGER = Logger.getLogger(JUTClasspathUtil.class);

	@Test
	public final void testGetClasspathResourcesByName() throws IOException
	{
		Map<String, ClasspathResource> classpathResources =
				ClasspathUtil.getClasspathResources();
		
		assertTrue(
				"expected more than 0 classpath resources",
				classpathResources.size() > 0);

		Set<String> sortedKeys = new TreeSet<>(classpathResources.keySet());
		
		for (String key : sortedKeys)
		{
			ClasspathResource classpathResource = classpathResources.get(key);

			LOGGER.debug(
					"resourcename, resource containerfile name: " +
					classpathResource.getResourcename() + ", " +
					classpathResource.getResourcecontainer()
					                 .getResourceContainerFile().getAbsolutePath());
		}
		
		LOGGER.debug("number of resources: " + classpathResources.size());
	}

	private final static String FILTERED_RESOURCE_CONTAINER_NAME =
			RuntimeUtil.JAVA_CLASS_PATH.split(RuntimeUtil.PATH_SEPARATOR)[0];

	@Test
	public final void testGetClasspathResourcesWithResourceContainerFilter()
			throws IOException
	{
		FileFilter resourceContainerFilter =
				new FileFilter()
				{
					@Override
					public boolean accept(File file)
					{
						if (file.getPath().equals(FILTERED_RESOURCE_CONTAINER_NAME))
						{
							LOGGER.debug("filtering resource container: " + FILTERED_RESOURCE_CONTAINER_NAME);
							return false;
						}
						return true;
					}
				};

		Map<String, ClasspathResource> classpathResourcesWithoutFilter =
				ClasspathUtil.getClasspathResources();
		Map<String, ClasspathResource> classpathResourcesWithFilter =
				ClasspathUtil.getClasspathResources(
						resourceContainerFilter,
						ClasspathUtil.FILTER_ACCEPT_FILES_ALL,
						ClasspathUtil.FILTER_ACCEPT_ZIP_ENTRIES_ALL);

		assertTrue(
				"expected less than " + classpathResourcesWithoutFilter.size() +
				" classpath resources",
				classpathResourcesWithoutFilter.size() > classpathResourcesWithFilter.size());

		LOGGER.debug(
				"\nnumber of resources with filter: " + classpathResourcesWithFilter.size() +
				"\nnumber of resources without filter: " + classpathResourcesWithoutFilter.size() +
				"\nclasspath\n" + RuntimeUtil.JAVA_CLASS_PATH);
	}

	@Test
	public final void testGetClasspathResourcesWithDirectoryResourceFilter()
			throws IOException
	{
		FileFilter resourceContainerFilter =
				// accept all resource containers
				ClasspathUtil.FILTER_ACCEPT_FILES_ALL;
//				ClasspathUtil.FILTER_ACCEPT_FILES_ALL_BUT_JAR;
		FileFilter directoryResourceFilter =
				ClasspathUtil.FILTER_ACCEPT_FILES_DIRECTORIES_ONLY;

		Map<String, ClasspathResource> classpathResourcesWithoutFilter =
				ClasspathUtil.getClasspathResources();
		Map<String, ClasspathResource> classpathResourcesWithFilter =
				ClasspathUtil.getClasspathResources(
						resourceContainerFilter,
						directoryResourceFilter,
						ClasspathUtil.FILTER_ACCEPT_ZIP_ENTRIES_ALL);

		assertTrue(
				"expected less than " + classpathResourcesWithoutFilter.size() +
				" classpath resources",
				classpathResourcesWithoutFilter.size() > classpathResourcesWithFilter.size());

		LOGGER.debug(
				"\nnumber of resources with filter: " + classpathResourcesWithFilter.size() +
				"\nnumber of resources without filter: " + classpathResourcesWithoutFilter.size());

		Set<String> sortedKeys = new TreeSet<>(classpathResourcesWithFilter.keySet());

		for (String key : sortedKeys)
		{
			ClasspathResource classpathResource = classpathResourcesWithFilter.get(key);

			LOGGER.debug(
					"resourcename, resource containerfile name: " +
					classpathResource.getResourcename() + ", " +
					classpathResource.getResourcecontainer()
					                 .getResourceContainerFile().getAbsolutePath());
		}
	}

	@Test
	public final void testGetClasspathPackages()
			throws IOException
	{
		Map<String, ClasspathResource> classpathResourcesWithoutFilter =
				ClasspathUtil.getClasspathResources();
		Map<String, ClasspathResource> classpathResourcesWithFilter =
				ClasspathUtil.getPackagesAsClasspathResources();

		assertTrue(
				"expected less than " + classpathResourcesWithoutFilter.size() +
				" classpath resources",
				classpathResourcesWithoutFilter.size() > classpathResourcesWithFilter.size());

		LOGGER.debug(
				"\nnumber of resources with filter: " + classpathResourcesWithFilter.size() +
				"\nnumber of resources without filter: " + classpathResourcesWithoutFilter.size());

		Set<String> sortedKeys = new TreeSet<>(classpathResourcesWithFilter.keySet());
		
		for (String key : sortedKeys)
		{
			ClasspathResource classpathResource = classpathResourcesWithFilter.get(key);

			LOGGER.debug(
					"resourcename, resource containerfile name: " +
					key + ", " +
//					classpathResource.getResourcename() + ", " +
					classpathResource.getResourcecontainer()
					                 .getResourceContainerFile().getAbsolutePath());
		}
		
		for (String key : sortedKeys)
		{
			Package pckg = Package.getPackage(key);
			
			if (pckg == null)
			{
				LOGGER.error("failure creating package for " + key);
			}
			else
			{
				LOGGER.debug("package: " + pckg.getName());
			}
		}
	}
	
	@Test
	public void getPackages()
			throws
					IOException,
					InstantiationException,
					IllegalAccessException,
					ClassNotFoundException
	{
		Map<String, ClasspathResource> packagesAsClasspathResources =
				ClasspathUtil.getPackagesAsClasspathResources();
		Map<String, Package> packages =
				ClasspathUtil.getPackages(packagesAsClasspathResources.keySet());
		
		assertTrue("expected more than 0 packages", packages.size() > 0);

		LOGGER.debug(
				"\nnumber of packages as classpath resources: " + packagesAsClasspathResources.size() +
				"\nnumber of packages: " + packages.size());
	}
}